﻿#include "UnstructuredMesh.h"
#include "MeshTool.h"
#include <libmesh/communicator.h>
#include <libmesh/mesh.h>
#include <libmesh/mesh_generation.h>

UnstructuredMesh::UnstructuredMesh(const Configuration& cfg)
  : Mesh(cfg)
  , _triangularization(Get<bool>("triangularization", false))

{
  _dims = GetVectorValue<int>("dims");
  if (cfg.Have("elem_type"))
  {
    _elem_type = Get<std::string>("elem_type");
  }
  else
  {
    if (_dims.size() == 2)
    {
      _elem_type = "QUAD4";
    }
    else if (_dims.size() == 3)
    {
      _elem_type = "HEX8";
    }
  }


  if (_dims.size() == 1)
  {
    console::Error("一维网格生成不支持");
  }
  else if (_dims.size() == 2)
  {
    _x_ranges = GetVectorValue<Real>("x_range");
    _y_ranges = GetVectorValue<Real>("y_range");
  }
  else if (_dims.size() == 3)
  {
    _x_ranges = GetVectorValue<Real>("x_range");
    _y_ranges = GetVectorValue<Real>("y_range");
    _z_ranges = GetVectorValue<Real>("z_range");
  }
  else
  {
    console::Error("dim设置错误");
  }
}

void UnstructuredMesh::Build()
{
  if (_prepared) //已经创建过
    return;

  libMesh::Parallel::Communicator comm;
  libMesh::Mesh other_mesh(comm);

  std::map<std::string, libMesh::ElemType> elem_type_map{
    { "TRI3", libMesh::ElemType::TRI3 },
    { "QUAD4", libMesh::ElemType::QUAD4 },
    { "TET4", libMesh::ElemType::TET4 },
    { "HEX8", libMesh::ElemType::HEX8 },
  };

  auto type = elem_type_map[_elem_type];

  if (_dims.size() == 2)
  {
    libMesh::MeshTools::Generation::build_cube(other_mesh,
                                               _dims[0],
                                               _dims[1],
                                               0,
                                               _x_ranges[0],
                                               _x_ranges[1],
                                               _y_ranges[0],
                                               _y_ranges[1],
                                               0,
                                               0,
                                               type);
  }

  if (_dims.size() == 3)
  {
    libMesh::MeshTools::Generation::build_cube(other_mesh,
                                               _dims[0],
                                               _dims[1],
                                               _dims[2],
                                               _x_ranges[0],
                                               _x_ranges[1],
                                               _y_ranges[0],
                                               _y_ranges[1],
                                               _z_ranges[0],
                                               _z_ranges[1],
                                               type);
  }

  MeshTool::Build(*this, other_mesh);

  Prepared();
}
